import React, { Component } from 'react';
import { Tabs } from 'antd';
import { DndProvider, DragSource, DropTarget, DropTargetMonitor } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';

interface TabNodeProps {
    children: any;
    connectDragSource: any;
    connectDropTarget: any;
    index?: number;
    moveTabNode?: Function;
}

interface CardSource {
    id: number;
    index: number;
}

const TabNode = (props: TabNodeProps) => {
  const { connectDragSource, connectDropTarget, children } = props;
  return connectDragSource(connectDropTarget(children));
}


const cardTarget = {
  drop(props: DraggableTabs, monitor: DropTargetMonitor) {
    const dragKey = monitor.getItem().index;
    const hoverKey = (props as any).index;

    if (dragKey === hoverKey) {
      return;
    }

    props.moveTabNode(dragKey, hoverKey);
    // eslint-disable-next-line no-param-reassign
    monitor.getItem().index = hoverKey;
  },
};

const cardSource = {
  beginDrag(props: CardSource) {
    return {
      id: props.id,
      index: props.index,
    };
  },
};

const WrapTabNode = DropTarget('DND_NODE', cardTarget, connect => ({
  connectDropTarget: connect.dropTarget(),
}))(
  DragSource('DND_NODE', cardSource, (connect, monitor) => ({
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging(),
  }))(TabNode),
);

interface DraggableTabsProps {
    index?: number;
    className?: string;
    hideAdd?: boolean;
    activeKey?: string;
    type?: "line" | "card" | "editable-card" | undefined;
    onEdit?: (e: React.MouseEvent | React.KeyboardEvent | string, action: 'add' | 'remove') => void;
    onTabClick?: (activeKey: string, e: React.KeyboardEvent | React.MouseEvent) => void;
}

interface DraggableTabsState {
    order: number[]
}

class DraggableTabs extends Component<DraggableTabsProps, DraggableTabsState> {

  state: DraggableTabsState = {
    order: [],
  };

  /**
   * 移动节点位置
   * @param dragKey 拖动的节点
   * @param hoverKey 浮动的节点
   */
  moveTabNode = (dragKey:number, hoverKey: number) => {
    const { order } = this.state;
    const newOrder = order.slice();
    const { children } = this.props;

    React.Children.forEach(children, (c: any) => {
      if (newOrder.indexOf(c.key) === -1) {
        newOrder.push(c.key);
      }
    });

    const dragIndex = newOrder.indexOf(dragKey);
    const hoverIndex = newOrder.indexOf(hoverKey);
    // 更新节点位置
    newOrder.splice(dragIndex, 1);
    newOrder.splice(hoverIndex, 0, dragKey);

    this.setState({
      order: newOrder,
    });
  };

  renderTabBar = (props: DraggableTabsProps, DefaultTabBar: any) => (
    <DefaultTabBar {...props}>
      {(node: any) => {
          return (
            <WrapTabNode key={node.key} index={node.key} moveTabNode={this.moveTabNode}>
              {node}
            </WrapTabNode>
          )
      }}
    </DefaultTabBar>
  );

  render() {
    const { order } = this.state;
    const { children } = this.props;

    const tabs: any = [];
    React.Children.forEach(children, c => {
      tabs.push(c);
    });

    const orderTabs = tabs.slice().sort((a: any, b: any) => {
      const orderA = order.indexOf(a.key);
      const orderB = order.indexOf(b.key);

      if (orderA !== -1 && orderB !== -1) {
        return orderA - orderB;
      }
      if (orderA !== -1) {
        return -1;
      }
      if (orderB !== -1) {
        return 1;
      }

      const ia = tabs.indexOf(a);
      const ib = tabs.indexOf(b);

      return ia - ib;
    });

    return (
      <DndProvider backend={HTML5Backend}>
        <Tabs renderTabBar={this.renderTabBar} {...this.props}>
          {orderTabs}
        </Tabs>
      </DndProvider>
    );
  }
}

export default DraggableTabs;
